package com.carnation.qa.socketserver.startup;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.carnation.qa.socketserver.common.util.MppContext;

public class SocketListener extends Thread {
	private final Log log = LogFactory.getLog(this.getClass());
	int socketPort;
	ServerSocket socketListener = null;

	HashMap<Socket, ServerThread> sockFacktory = new HashMap<Socket, ServerThread>();

	public SocketListener() {
		socketPort = MppContext.getInt("mpp.socketPort", -1);
	}

	public boolean init() throws IOException {
		if (socketPort >= 0) {
			socketListener = new ServerSocket(socketPort);
			return true;
		}
		return false;

	}

	public synchronized void close() {
		if (socketListener != null) {
			try {
				socketListener.close();
			} catch (IOException e) {
			}
			socketListener = null;
			ArrayList<ServerThread> opendSocket = new ArrayList<ServerThread>(
					sockFacktory.values());
			Iterator<ServerThread> it = opendSocket.iterator();
			while (it.hasNext()) {
				ServerThread svr = it.next();
				svr.shutdown();
			}
			sockFacktory.clear();
		}
	}

	public void finalize() throws Throwable {
		close();
		super.finalize();
	}

	public void interrupt() {
		close();
		super.interrupt();
	}

	public void run() {
		while (true) {
			Socket soc = null;
			try {
				soc = socketListener.accept();
				ServerThread svr = new ServerThread(this, soc);
				synchronized (this) {
					sockFacktory.put(soc, svr);
				}
				svr.start();
			} catch (IOException e) {
				if (log.isErrorEnabled()) {
					log.error(e);
				}
				// System.out.println(e.toString());
				break;
			}
			// create New
		}
	}

	synchronized void shudownSock(Socket socket) {
		sockFacktory.remove(socket);
	}

	public int getSocketPort() {
		return socketPort;
	}

	public void setSocketPort(int socketPort) {
		this.socketPort = socketPort;
	}

	public void BroadMessage(String msg) {
		ArrayList<ServerThread> ServerThread = null;
		synchronized (this) {
			ServerThread = new ArrayList<ServerThread>(sockFacktory.values());
		}
		Iterator<ServerThread> it = ServerThread.iterator();
		while (it.hasNext()) {
			ServerThread svr = it.next();
			// 可以考虑用多线程发送
			try {
				svr.writePackage(msg);
			} catch (IOException e) {
				// socket被关闭
				if (log.isErrorEnabled()) {
					log.error(e);
				}
				svr.shutdown();
			}
		}
	}

	public static void main(String args[]) throws IOException {
		int port = MppContext.getSocketserverListenerPort();
		if (args.length == 1) {
			try {
				port = Integer.parseInt(args[0]);
			} catch (NumberFormatException e) {
				System.err.println(e);
			}
		}
		long t1 = System.currentTimeMillis();
		SocketListener svr = new SocketListener();
		svr.setSocketPort(port);
		if (svr.log.isInfoEnabled()) {
			svr.log.info("Starting Socket Server on TCP/IP-" + port);
		}
		boolean isRun = svr.init();
		if (isRun) {
			svr.start();
			long t2 = System.currentTimeMillis();
			// svr.close();
			if (svr.log.isInfoEnabled()) {
				svr.log.info("Socket Server startup in " + (t2 - t1) + " ms");
			}
		}
	}
}
